﻿using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

using Perseus.Data;

using Hetymine.Executioner.Data;

namespace Hetymine.Executioner.Controls {
    /// <summary>
    /// Interaction logic for AppearanceConfigurator.xaml
    /// </summary>
    public partial class AppearanceConfigurator : UserControl, IConfigurator<IniFile> {
        private IniFile _Config;
        private bool _IsApply = true;
        private System.Windows.Forms.FontDialog _FontDialog = new System.Windows.Forms.FontDialog();        

        public AppearanceConfigurator() {
            InitializeComponent();

            // Outer Border
            this.cOuterBorderColour.TextChanged += new TextChangedEventHandler(Colour_TextChanged);
            this.cOuterBorderWidth.TextChanged += new TextChangedEventHandler(Width_TextChanged);
            this.cOuterBorderRadius.TextChanged += new TextChangedEventHandler(Width_TextChanged);

            // Inner Border
            this.cInnerBorderColour.TextChanged += new TextChangedEventHandler(Colour_TextChanged);
            this.cInnerBorderWidth.TextChanged += new TextChangedEventHandler(Width_TextChanged);
            this.cInnerBorderRadius.TextChanged += new TextChangedEventHandler(Width_TextChanged);

            // Command Box
            this.cFont.Click += new RoutedEventHandler(Font_Click);
            this.cFontFamily.TextChanged += new TextChangedEventHandler(FontFamily_TextChanged);
            this.cFontSize.TextChanged += new TextChangedEventHandler(FontSize_TextChanged);
            this.cBold.Click += new RoutedEventHandler(FontStyle_Click);
            this.cItalic.Click += new RoutedEventHandler(FontStyle_Click);
            this.cBackgroundColour.TextChanged += new TextChangedEventHandler(Colour_TextChanged);
            this.cForegroundColour.TextChanged += new TextChangedEventHandler(Colour_TextChanged);

            // Alignment and Padding
            this.cMargin.TextChanged += new TextChangedEventHandler(Margin_TextChanged);
            this.cPadding.TextChanged += new TextChangedEventHandler(Width_TextChanged);
            this.cAlignment.SelectionChanged += new SelectionChangedEventHandler(Alignment_SelectionChanged);
        }
    
        private void Font_Click(object sender, RoutedEventArgs e) {
            int size;
            if (!int.TryParse(this.cFontSize.Text, out size)) {
                size = 14;
            }
            System.Drawing.FontStyle style = System.Drawing.FontStyle.Regular;
            if (this.cBold.IsChecked.Value) {
                style |= System.Drawing.FontStyle.Bold;
            }
            if (this.cItalic.IsChecked.Value) {
                style |= System.Drawing.FontStyle.Italic;
            }
            this._FontDialog.Font = new System.Drawing.Font(
                this.cFontFamily.Text,
                size,
                style
            );
            this._FontDialog.ShowDialog();

            this.cFontFamily.Text = this._FontDialog.Font.FontFamily.Name;
            this.cFontSize.Text = ((int)Math.Round(this._FontDialog.Font.Size, MidpointRounding.AwayFromZero)).ToString();
            this.cBold.IsChecked = this._FontDialog.Font.Bold;
            this.cItalic.IsChecked = this._FontDialog.Font.Italic;
        }

        private void Colour_TextChanged(object sender, RoutedEventArgs e) {
            if (!this._IsApply) { return; }

            TextBox t = sender as TextBox;

            if (!Regex.IsMatch(t.Text, "^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$")) {
                t.Background = Brushes.LightPink;
            }
            else {
                t.Background = SystemColors.ControlLightLightBrush;

                switch (t.Name) {
                    case "cOuterBorderColour":
                        this._Config.SetString("Appearance", "Outer Border Colour", t.Text.ToUpper());
                        break;
                    case "cInnerBorderColour":
                        this._Config.SetString("Appearance", "Inner Border Colour", t.Text.ToUpper());
                        break;
                    case "cBackgroundColour":
                        this._Config.SetString("Appearance", "Background Colour", t.Text.ToUpper());
                        break;
                    case "cForegroundColour":
                        this._Config.SetString("Appearance", "Foreground Colour", t.Text.ToUpper());
                        break;
                }

                this.UpdatePreview();
            }
        }
        private void Width_TextChanged(object sender, TextChangedEventArgs e) {
            if (!this._IsApply) { return; }

            TextBox t = sender as TextBox;

            bool valid = true;

            int value;
            if (!int.TryParse(t.Text, out value)) {
                valid = false;
            }
            else if (value < 0) {
                valid = false;
            }

            if (!valid) {
                t.Background = Brushes.LightPink;
            }
            else {
                if (value > 10) {
                    t.Background = Brushes.LightYellow;
                }
                else {
                    t.Background = SystemColors.ControlLightLightBrush;
                }

                switch (t.Name) {
                    case "cOuterBorderWidth":
                        this._Config.SetInt("Appearance", "Outer Border Width", value);
                        break;
                    case "cInnerBorderWidth":
                        this._Config.SetInt("Appearance", "Inner Border Width", value);
                        break;
                    case "cOuterBorderRadius":
                        this._Config.SetInt("Appearance", "Outer Border Radius", value);
                        break;
                    case "cInnerBorderRadius":
                        this._Config.SetInt("Appearance", "Inner Border Radius", value);
                        break;
                    case "cPadding":
                        this._Config.SetInt("Appearance", "Padding", value);
                        break;
                }

                this.UpdatePreview();
            }
        }
        private void FontFamily_TextChanged(object sender, TextChangedEventArgs e) {
            if (!this._IsApply) { return; }

            TextBox t = sender as TextBox;
            System.Drawing.FontFamily fm = new System.Drawing.FontFamily(t.Text.Trim());

            if (fm.Name != this.cFontFamily.Text.Trim()) {
                t.Background = Brushes.LightPink;
            }
            else {
                t.Background = SystemColors.ControlLightLightBrush;
                this._Config.SetString("Appearance", "Font Family", fm.Name);
                this.UpdatePreview();
            }
        }
        private void FontSize_TextChanged(object sender, TextChangedEventArgs e) {
            if (!this._IsApply) { return; }

            TextBox t = sender as TextBox;

            bool valid = true;

            int value;
            if (!int.TryParse(t.Text, out value)) {
                valid = false;
            }
            else if (value < 6) {
                valid = false;
            }

            if (!valid) {
                t.Background = Brushes.LightPink;
            }
            else {
                if (value > 72) {
                    t.Background = Brushes.LightYellow;
                }
                else {
                    t.Background = SystemColors.ControlLightLightBrush;
                }

                this._Config.SetInt("Appearance", "Font Size", value);

                this.UpdatePreview();
            }
        }        
        private void FontStyle_Click(object sender, RoutedEventArgs e) {
            if (!this._IsApply) { return; }

            string style;

            if (this.cBold.IsChecked.Value) {
                style = "bold";

                if (this.cItalic.IsChecked.Value) {
                    style += ", italic";
                }
            }
            else if (this.cItalic.IsChecked.Value) {
                style = "italic";
            }
            else {
                style = "regular";
            }

            this._Config.SetString("Appearance", "Font Style", style);

            this.UpdatePreview();
        }
        private void Margin_TextChanged(object sender, TextChangedEventArgs e) {
            if (!this._IsApply) { return; }

            TextBox t = sender as TextBox;

            bool valid = true;

            int value;
            if (!int.TryParse(t.Text, out value)) {
                valid = false;
            }
            else if (value < 0) {
                valid = false;
            }

            if (!valid) {
                t.Background = Brushes.LightPink;
            }
            else {
                System.Drawing.Rectangle r = Styles.Display().WorkingArea;
                int max = (int)((Math.Min(r.Width, r.Height) - 300) / 2);
                if (value > max) {
                    t.Background = Brushes.LightYellow;
                }
                else {
                    t.Background = SystemColors.ControlLightLightBrush;
                }

                this._Config.SetInt("Appearance", "Margin", value);
            }
        }
        private void Alignment_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            if (!this._IsApply) { return; }

            ComboBoxItem cb = e.AddedItems[0] as ComboBoxItem;
            string alignment = cb.Content.ToString().ToLower();
            this._Config.SetString("Appearance", "Alignment", alignment);
        }
        
        private void UpdatePreview() {
            Styles.OuterBorder(this.cPreviewOuterBorder, this._Config);
            Styles.InnerBorder(this.cPreviewInnerBorder, this._Config);
            Styles.TextBox(this.cPreviewCommandTextBox, this._Config);
        }
        private int AppearanceAlignmentIndex() {
            string a = this._Config.GetString("Appearance", "Alignment", "centre centre").ToLower();
            switch (a) {
                case "left top":
                case "top left":
                    return 0;
                case "centre top":
                case "center top":
                case "top centre":
                case "top center":
                    return 1;
                case "right top":
                case "top right":
                    return 2;
                case "left centre":
                case "left center":
                case "centre left":
                case "center left":
                    return 3;
                case "right centre":
                case "right center":
                case "centre right":
                case "center right":
                    return 5;
                case "left bottom":
                case "bottom left":
                    return 6;
                case "centre bottom":
                case "center bottom":
                case "bottom centre":
                case "bottom center":
                    return 7;
                case "right bottom":
                case "bottom right":
                    return 8;
                default:
                    return 4;
            }
        }

        #region IConfigurator<IniFile> Members
        public void InitializeConfig(IniFile config) {
            this._Config = config;
            
            this._IsApply = false;

            // Outer border
            this.cOuterBorderColour.Text = this._Config.GetString("Appearance", "Outer Border Colour", "#313131").ToUpper();
            this.cOuterBorderWidth.Text = this._Config.GetInt("Appearance", "Outer Border Width", 2).ToString();
            this.cOuterBorderRadius.Text = this._Config.GetInt("Appearance", "Outer Border Radius", 6).ToString();

            // Inner border
            this.cInnerBorderColour.Text = this._Config.GetString("Appearance", "Inner Border Colour", "#FBC23E").ToUpper();
            this.cInnerBorderWidth.Text = this._Config.GetInt("Appearance", "Inner Border Width", 2).ToString();
            this.cInnerBorderRadius.Text = this._Config.GetInt("Appearance", "Inner Border Radius", 4).ToString();

            // Command box
            this._FontDialog.ShowColor = false;
            this._FontDialog.ShowApply = false;
            this._FontDialog.ShowEffects = false;
            this._FontDialog.ShowHelp = false;
            this._FontDialog.FontMustExist = true;

            System.Drawing.Font f = Styles.Font(this._Config);
            this.cBold.IsChecked = f.Bold;
            this.cItalic.IsChecked = f.Italic;
            this.cFontFamily.Text = f.FontFamily.Name;
            this.cFontSize.Text = ((int)Math.Round(f.Size, MidpointRounding.AwayFromZero)).ToString();
            this._FontDialog.Font = f;

            this.cBackgroundColour.Text = this._Config.GetString("Appearance", "Background Colour", "#313131").ToUpper();
            this.cForegroundColour.Text = this._Config.GetString("Appearance", "Foreground Colour", "#FBC23E").ToUpper();

            // Alignment and padding
            this.cMargin.Text = this._Config.GetInt("Appearance", "Margin", 10).ToString();
            this.cPadding.Text = this._Config.GetInt("Appearance", "Padding", 3).ToString();
            this.cAlignment.SelectedIndex = this.AppearanceAlignmentIndex();

            this._IsApply = true;

            this.UpdatePreview();
        }
        public UserControl ConfigPanel { get { return this; } }
        #endregion
    }
}
